package com.thyme.system.rest;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.thyme.common.base.ApiResponse;
import com.thyme.common.utils.Ftp;
import com.thyme.common.utils.MultipartFileToFile;
import com.thyme.system.service.*;
import com.thyme.system.vo.*;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.annotations.Param;
import org.apache.log4j.Logger;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;

/**
 * @author thyme
 * @ClassName MenuController
 * @Description TODO
 * @Date 2019/12/30 15:03
 */
@RestController
@RequestMapping("/ICDImportConfig")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ICDImportConfigRestController {
    private static Logger logger = Logger.getLogger(ICDImportConfigRestController.class.getName());
    private final Iec61850IedInstService iec61850IedInstService;
    private final Iec61850DataInstService iec61850DataInstService;
    private final Iec61850IedService iec61850IedService;
    private final Iec61850LdService iec61850LdService;
    private final Iec61850LnService iec61850LnService;
    private final Iec61850DoService iec61850DoService;


    @GetMapping("/getConfigInfo")
    public ApiResponse getConfigInfo(@RequestParam("page") int page,
                                     @RequestParam("page_size") int pageSize) {
        JSONObject jsonObject = new JSONObject();
        IPage<Iec61850IedInstVo> sysConfigList = iec61850IedInstService.getAll(new Page(page, pageSize));
        jsonObject.put("total", sysConfigList.getTotal());
        jsonObject.put("page", sysConfigList.getCurrent());
        jsonObject.put("page_size", sysConfigList.getSize());
        jsonObject.put("sysConfigList", sysConfigList.getRecords());
        return ApiResponse.ofSuccess(jsonObject);
    }

    @GetMapping("/getLEDList")
    public ApiResponse getLEDList() {
        JSONObject jsonObject = new JSONObject();
        List<IedNameEnumVO> selectOption = iec61850IedInstService.getLEDNameEnumList();
        jsonObject.put("selectOption", selectOption);
        return ApiResponse.ofSuccess(jsonObject);
    }


    @GetMapping("/getNodeInfo")
    public ApiResponse getNodeInfo(@RequestParam("page") int page,
                                   @RequestParam("page_size") int pageSize, @RequestParam("iedId") Integer iedId) {
        JSONObject jsonObject = new JSONObject();
        IPage<Iec61850NodeDataVo> sysNodeList = iec61850DataInstService.getAll(new Page(page, pageSize), iedId);
        jsonObject.put("total", sysNodeList.getTotal());
        jsonObject.put("page", sysNodeList.getCurrent());
        jsonObject.put("page_size", sysNodeList.getSize());
        jsonObject.put("sysNodeList", sysNodeList.getRecords());
        return ApiResponse.ofSuccess(jsonObject);
    }

    @GetMapping("/deleteConfig")
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public ApiResponse deleteConfig(@RequestParam("id") Integer id) {
        JSONObject jsonObject = new JSONObject();
        try {
            iec61850IedInstService.deleteByConfigId(id);
            iec61850DataInstService.deleteByConfigId(id);
            jsonObject.put("code", 200);
        } catch (Exception e) {
            jsonObject.put("code", 500);
            e.printStackTrace();
        }
        return ApiResponse.ofSuccess(jsonObject);
    }

    @GetMapping("/remoteUploadConfig")
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public ApiResponse remoteUploadConfig(@RequestParam("iedName") Integer iedName) {
        JSONObject jsonObject = new JSONObject();
        try {
            Ftp ftp = new Ftp("146.56.235.116", 21, "ftpuser", "tf7295TFY");
            ftp.ftpLogin();
            InputStream in = ftp.readFile("IEC61850C_App.ini", "/var/ftp/test");
            if (in != null) {
                BufferedReader br = new BufferedReader(new InputStreamReader(in, "gb2312"));
                String data = null;
                while ((data = br.readLine()) != null) {

                }

            } else {

//              ftp.uploadFile(iedName + ".ICD", normFile, "/var/ftp/test");
            }
            ftp.ftpLogOut();
            jsonObject.put("code", 200);
        } catch (Exception e) {
            jsonObject.put("code", 500);
            e.printStackTrace();
        }
        return ApiResponse.ofSuccess(jsonObject);
    }

    @PostMapping("/updateConfig")
    @ResponseBody
    public ApiResponse updateConfig(@RequestBody Iec61850IedVo iec61850IedVo) {
        JSONObject jsonObject = new JSONObject();
        Iec61850IedInstVo iec61850IedInstVo = new Iec61850IedInstVo(iec61850IedVo.getId(), iec61850IedVo.getIedName(), iec61850IedVo.getIedDesc(), iec61850IedVo.getIedIp(), iec61850IedVo.getIedState());
        try {
            if (iec61850IedInstVo.getIedState()) {
                iec61850IedInstVo.setUpdateStateTimestamp(new Date());
            }
            if (iec61850IedInstService.updateConfig(iec61850IedInstVo)) {
                jsonObject.put("code", 200);
            }
        } catch (Exception e) {
            e.printStackTrace();
            jsonObject.put("code", 500);
        }
        return ApiResponse.ofSuccess(jsonObject);
    }

    @PostMapping("importIcd")
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public ApiResponse importIec61850IedInst(@Param("file") MultipartFile file) throws Exception {
        if (file.isEmpty()) {
            return ApiResponse.fail("导入数据为空");
        }
        InputStream inputStream = file.getInputStream();

        //导入数据库测量量文件
        getSelXml2(inputStream);
//        Iec61850IedInstVo iec61850IedInstVo = (Iec61850IedInstVo) map.get("iec61850IedInstVo");
//        iec61850IedInstVo.setFileName(file.getOriginalFilename());
//        Set<Iec61850DataInstVo> iec61850DataInstVos = (Set<Iec61850DataInstVo>) map.get("iec61850DataInstVos");
//        List<Iec61850LdVo> idVoList = (List<Iec61850LdVo>) map.get("idVoList");
        /**
         * 插入ied到所有配置到数据库
         */
//        iec61850IedInstService.insert(iec61850IedInstVo, iec61850DataInstVos,idVoList);
        /**
         * 远程上传文件
         */
        //调用
        File normFile = null;
        try {
            //将MultipartFile转为File
            normFile = MultipartFileToFile.multipartFileToFile(file);
            Ftp ftp = new Ftp("146.56.235.116", 21, "ftpuser", "tf7295TFY");
            ftp.ftpLogin();
            ftp.uploadFile(file.getOriginalFilename() + ".ICD", normFile, "/var/ftp/test");
            ftp.ftpLogOut();

        } catch (Exception e) {
            e.printStackTrace();
            return ApiResponse.fail("上传失败，请检查文件格式再次尝试");
        } finally {
            MultipartFileToFile.deleteTempFile(normFile);
        }


//            List<YclysEntityDto> entityList = (List<YclysEntityDto>) map.get("entityList");
//            List<YclysEntityDto> iedData = entityList.stream().filter(s -> !s.getDAtypeName().equals("q") && !s.getDAtypeName().equals("t")).collect(Collectors.toList());
//            iec61850DataInstManager.updataDB(iedData);
//
//            // 同步节点名称配置到数据库
//            List<Iec61850LnInstVO> jdNameList = (List<Iec61850LnInstVO>) map.get("JDNameList");
//
//            for (Iec61850LnInstVO iec61850LnInstVO : jdNameList) {
//                Iec61850LnInst temp_entity = new Iec61850LnInst();
//                BeanUtil.copyProperties(temp_entity, iec61850LnInstVO);
//                temp_entity.setIedDesc(temp_entity.getIedDesc().replace('△', 'D'));
//                // 更新至数据库
//                int count = iIec61850LnInstService.getLnCount(temp_entity.getIedName(), temp_entity.getLdInstName(), temp_entity.getLnInstName());
//                if (count > 0) {
//                    // 已存在id则修改
//                    iIec61850LnInstService.updateIec61850LnInst(temp_entity);
//                } else {
//                    iIec61850LnInstService.createIec61850LnInst(temp_entity);
//                }
//            }

//            //写入icd文件
//            File icdFile = new File(osicfgLocalUrl + dir_iedName + File.separator + fileName);
//            OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(icdFile), "UTF-8");
//            PrintWriter pw = new PrintWriter(os);
//            in2.close();
//            is.close();
//            for (String s : str_output) {
//                pw.println(s);
//            }
//            pw.close();
//            os.close();
        return ApiResponse.success("ok");
    }


    public void getSelXml2(InputStream inSt) throws Exception {
        Iec61850IedInstVo iec61850IedInstVo = new Iec61850IedInstVo();
        Element root = new SAXBuilder().build(inSt).getRootElement();
        Namespace ns = root.getNamespace();
        Element communication = root.getChild("Communication", ns);
        Element subNetwork = communication.getChild("SubNetwork", ns);
        Element connectedAP = subNetwork.getChild("ConnectedAP", ns);
        String apName = connectedAP.getAttributeValue("apName");
        String iedName = connectedAP.getAttributeValue("iedName");
        Element address = connectedAP.getChild("Address", ns);
        List<Element> addressList = address.getChildren("P", ns);
        String ip = "";
        List<Element> IEDList = root.getChildren("IED", ns);

        String ied_name = IEDList.get(0).getAttributeValue("name") == null ? "" : IEDList.get(0).getAttributeValue("name");
        String ied_desc = IEDList.get(0).getAttributeValue("desc") == null ? "" : IEDList.get(0).getAttributeValue("desc");
        int iedId = -1;
        for (Element e1 : addressList) {
            String type = e1.getAttributeValue("type");
            if ("IP".equals(type)) {
                ip = e1.getText();

                if (iedName.equals(ied_name)) {
                    //todo ied_name ied_ied_desc ied_ip地址导入数据库
                    iec61850IedInstVo.setIedName(iedName);
                    iec61850IedInstVo.setIedDesc(ied_desc);
                    iec61850IedInstVo.setIedIp(ip);

                    // ied   todo
                    Iec61850IedVo iedVo = new Iec61850IedVo(iedName, ied_desc, ip);
                    iedId = iec61850IedService.updateIED(iedVo);
                } else {
                    throw new Exception("配置文件中ied名称配置不正确");
                }

            }
        }


        for (Element el : IEDList) {
            // 开始循环, 创建一个YclysEntity对象
            Element AccessPoint = el.getChild("AccessPoint", ns);
            Element Server = AccessPoint.getChild("Server", ns);
            List<Element> LDevice = Server.getChildren("LDevice", ns);
            // 开始遍历每个LD
            for (Element el_ld : LDevice) {
                String ld_inst = el_ld.getAttributeValue("inst") == null ? "" : el_ld.getAttributeValue("inst");
                String ld_desc = el_ld.getAttributeValue("desc") == null ? "" : el_ld.getAttributeValue("desc");

                // todo  ld
                Iec61850LdVo iec61850LdVo = new Iec61850LdVo(ld_inst, ld_desc, iedId);
                int LDId = iec61850LdService.updateLD(iec61850LdVo);
                // 解析逻辑节点
                List<Element> lnList = el_ld.getChildren("LN", ns);
//                     开始遍历每个LN
                for (Element el2 : lnList) {

                    String ln_prefix = el2.getAttributeValue("prefix") == null ? "" : el2.getAttributeValue("prefix");
                    String ln_Type = el2.getAttributeValue("lnType") == null ? "" : el2.getAttributeValue("lnType");
                    String ln_Class = el2.getAttributeValue("lnClass") == null ? "" : el2.getAttributeValue("lnClass");
                    String ln_inst = el2.getAttributeValue("inst") == null ? "" : el2.getAttributeValue("inst");
                    String ln_desc = el2.getAttributeValue("desc") == null ? "" : el2.getAttributeValue("desc");

                    String vendor = "";
                    String devFuncCode = "";
                    String model = "";
                    String sn = "";
                    String manDate = "";
                    String runDate = "";

                    List<Element> DOList = el2.getChildren("DOI", ns);
                    //todo LN 描述信息
                    for (Element elementDO : DOList) {
                        String nameDO = elementDO.getAttributeValue("name") == null ? "" : elementDO.getAttributeValue("name");
                        if ("PhyNam".equals(nameDO)||"NamPlt".equals(nameDO)) {
                            List<Element> DAList = elementDO.getChildren("DAI", ns);
                            for (Element elementDA : DAList) {
                                String nameDA = elementDA.getAttributeValue("name") == null ? "" : elementDA.getAttributeValue("name");
                                if ("vendor".equals(nameDA)) {
                                    List<Element> DAIVal = elementDA.getChildren("Val", ns);
                                    if (DAIVal.size() > 0) {
                                        vendor = DAIVal.get(0).getText();
                                    }
                                } else if ("devFuncCode".equals(nameDA)) {
                                    List<Element> DAIVal = elementDA.getChildren("Val", ns);
                                    if (DAIVal.size() > 0) {
                                        devFuncCode = DAIVal.get(0).getText();
                                    }
                                } else if ("manDate".equals(nameDA)) {
                                    List<Element> DAIVal = elementDA.getChildren("Val", ns);
                                    if (DAIVal.size() > 0) {
                                        manDate = DAIVal.get(0).getText();
                                    }
                                } else if ("runDate".equals(nameDA)) {
                                    List<Element> DAIVal = elementDA.getChildren("Val", ns);
                                    if (DAIVal.size() > 0) {
                                        runDate = DAIVal.get(0).getText();
                                    }
                                } else if ("model".equals(nameDA)) {
                                    List<Element> DAIVal = elementDA.getChildren("Val", ns);
                                    if (DAIVal.size() > 0) {
                                        model = DAIVal.get(0).getText();
                                    }
                                } else if ("sn".equals(nameDA)) {
                                    List<Element> DAIVal = elementDA.getChildren("Val", ns);
                                    if (DAIVal.size() > 0) {
                                        sn = DAIVal.get(0).getText();
                                    }
                                }
                            }
                        }
                    }
                    int LnId = -1;
                    if (!ln_Type.contains("LPHD")) {
                        Iec61850LnVo iec61850LnVo = new Iec61850LnVo(ln_prefix + ln_Class + ln_inst, ln_desc, LDId, vendor, devFuncCode);
                        // todo ln
                        LnId = iec61850LnService.updateLn(iec61850LnVo);
                    }else{
                        iec61850LdVo.setSn(sn);
                        iec61850LdVo.setModel(model);
                        iec61850LdVo.setManDate(manDate);
                        iec61850LdVo.setRunDate(runDate);
                        iec61850LdService.updateLD(iec61850LdVo);
                    }
                    List<Element> ln0List = el_ld.getChildren("LN0", ns);
                    List<Element> dataSetList = ln0List.get(0).getChildren("DataSet", ns);
                    //解析FCDA数据
                    for (Element data : dataSetList) {
                        List<Element> dataFCDAList = data.getChildren("FCDA", ns);
                        for (Element element : dataFCDAList) {
                            String ldInstFCDA = element.getAttributeValue("ldInst") == null ? "" : element.getAttributeValue("ldInst");
                            String prefixFCDA = element.getAttributeValue("prefix") == null ? "" : element.getAttributeValue("prefix");
                            String lnClassFCDA = element.getAttributeValue("lnClass") == null ? "" : element.getAttributeValue("lnClass");
                            String lnInstFCDA = element.getAttributeValue("lnInst") == null ? "" : element.getAttributeValue("lnInst");
                            String descDO = "";
                            if ((prefixFCDA + lnClassFCDA + lnInstFCDA).equals(ln_prefix + ln_Class + ln_inst)) {
                                String doNameFCDA = element.getAttributeValue("doName") == null ? "" : element.getAttributeValue("doName");
                                String fcFCDA = element.getAttributeValue("fc") == null ? "" : element.getAttributeValue("fc");
//                                List<Element> DOList = el2.getChildren("DOI", ns);
                                //todo LN 描述信息
                                for (Element element1 : DOList) {
                                    String doName = element1.getAttributeValue("name") == null ? "" : element1.getAttributeValue("name");
                                    if (doNameFCDA.equals(doName)) {
                                        descDO = element1.getAttributeValue("desc") == null ? "" : element1.getAttributeValue("desc");
                                        List<Element> DAList = element1.getChildren("DAI", ns);
                                        for (Element elementDA : DAList) {
                                            String nameDA = elementDA.getAttributeValue("name") == null ? "" : elementDA.getAttributeValue("name");
                                            if ("dU".equals(nameDA)) {
                                                List<Element> DAIVal = elementDA.getChildren("Val", ns);
                                                if (DAIVal.size() > 0) {
                                                    descDO = DAIVal.get(0).getText();
                                                }
                                            }

                                        }
                                    }

                                }

                                Iec61850DoVo iec61850DoVo = new Iec61850DoVo(ied_name + ldInstFCDA + "/" + prefixFCDA + lnClassFCDA + lnInstFCDA + "$" + fcFCDA + "$" + doNameFCDA,
                                        doNameFCDA, descDO, fcFCDA, LnId);
                                iec61850DoService.updateDo(iec61850DoVo);
                            }
                        }

                    }

                }
            }
        }
    }
}
